﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using AMail.Common;
using AMail.Common.Events;
using AMail.Common.Interfaces.Data;
using AMail.Common.Interfaces.Services;
using AMail.Modules.Folders.Interfaces;
using Elentok.Common.Wpf;
using Elentok.Common.Wpf.Helpers;
using Elentok.Common.Wpf.ViewModels.Dialogs;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Commands;

namespace AMail.Modules.Folders.ViewModels
{
  public class FoldersTreeViewModel : ViewModelBase, IFoldersTreeViewModel
  {
    #region Private Data Members

    private IDataService dataService;
    private IEventAggregator eventAggregator;
    private IMailFolder rootFolder;
    private IFolderViewModel selectedFolder;

    #endregion

    public FoldersTreeViewModel(IEventAggregator eventAggregator, IDataService dataService)
    {
      this.RootFolders = new ObservableCollection<IFolderViewModel>();
      this.dataService = dataService;
      this.eventAggregator = eventAggregator;
      this.eventAggregator.GetEvent<ActiveArchiveChangedEvent>().Subscribe(OnActiveArchiveChanged);

      this.CreateSubfolderCommand = new DelegateCommand<object>(
        ExecuteCreateSubfolderCommand, CanExecuteCreateSubfolderCommand);
      this.DeleteFolderCommand = new DelegateCommand<object>(
        ExecuteDeleteFolderCommand, CanExecuteDeleteFolderCommand);
      this.RenameFolderCommand = new DelegateCommand<object>(
        ExecuteRenameFolderCommand, CanExecuteRenameFolderCommand);
    }

    public ObservableCollection<IFolderViewModel> RootFolders { get; private set; }

    /// <summary>
    /// Gets or sets the selectedFolder
    /// </summary>
    public IFolderViewModel SelectedFolder
    {
      get
      {
        return this.selectedFolder;
      }
      set
      {
        if (this.selectedFolder == value)
          return;

        OnPropertyChanging("SelectedFolder");
        this.selectedFolder = value;
        OnPropertyChanged("SelectedFolder");

        IMailFolder folder = null;
        if (this.selectedFolder != null)
          folder = this.selectedFolder.Folder;
        this.eventAggregator.GetEvent<SelectedFolderChangedEvent>().Publish(folder);
      }
    }

    #region Helper Methods


    private void OnActiveArchiveChanged(ActiveArchiveChangedEventArgs eventArgs)
    {
      if (eventArgs.NewArchive == null)
        RootFolder = null;
      else
        RootFolder = eventArgs.NewArchive.Root;

      
    }

    #region Create Subfolder Command
    private void ExecuteCreateSubfolderCommand(object param)
    {
      var viewModel = new InputDialogViewModel
      {
        Title = "Create subfolder",
        Message = "Enter the name of the new folder"
      };

      var dialog = new Dialog(viewModel);

      if (dialog.ShowDialog() == true)
      {
        IMailFolder subfolder = this.dataService.CreateFolder();
        subfolder.Name = viewModel.InputText;
        this.selectedFolder.Folder.Subfolders.Add(subfolder);
      }
    }

    private bool CanExecuteCreateSubfolderCommand(object param)
    {
      return this.selectedFolder != null;
    }
    #endregion

    #region Delete Folder Command
    private void ExecuteDeleteFolderCommand(object param)
    {
      IMailFolder folder = this.selectedFolder.Folder;

      MessageBoxResult result =
        MessageBox.Show(
        "Delete folder '" + folder.Name + "'?",
        "AMail - Confirmation",
        MessageBoxButton.YesNo, MessageBoxImage.Question);

      if (result == MessageBoxResult.Yes)
        folder.ParentFolder.Subfolders.Remove(folder);
    }

    private bool CanExecuteDeleteFolderCommand(object param)
    {
      return this.selectedFolder != null && 
        this.selectedFolder.Parent != null;
    }
    #endregion

    #region Rename Folder Command
    private void ExecuteRenameFolderCommand(object param)
    {
      var viewModel = new InputDialogViewModel
      {
        Title = "Rename folder",
        Message = "Enter the new name of the folder",
        InputText = selectedFolder.Folder.Name
      };

      var dialog = new Dialog(viewModel);

      if (dialog.ShowDialog() == true)
      {
        this.selectedFolder.Header = viewModel.InputText;
      }
    }

    private bool CanExecuteRenameFolderCommand(object param)
    {
      return this.selectedFolder != null &&
        this.selectedFolder.Parent != null;
    }
    #endregion

    #endregion

    #region IFoldersTreeViewModel Members

    /// <summary>
    /// Gets or sets the root folder
    /// </summary>
    public IMailFolder RootFolder
    {
      get
      {
        return this.rootFolder;
      }
      set
      {
        if (this.rootFolder == value)
          return;

        this.rootFolder = value;

        this.RootFolders.Clear();
        if (value != null)
        {
          var rootFolderViewModel = new FolderViewModel(value, null);
          rootFolderViewModel.IsExpanded = true;
          rootFolderViewModel.IsSelected = true;
          this.RootFolders.Add(rootFolderViewModel);
        }

        OnPropertyChanged("RootFolder");
      }
    }

    public ICommand CreateSubfolderCommand { get; private set; }
    public ICommand DeleteFolderCommand { get; private set; }
    public ICommand RenameFolderCommand { get; private set; }


    public bool CanDrop(IFolderViewModel targetFolder, IDataObject data)
    {
      var messages = data.GetData<List<IMailMessage>>();

      if (messages != null && messages.Count > 0)
      {
        if (messages[0] is IMailMessage)
        {
          foreach (IMailMessage message in messages)
          {
            if (message.ParentFolder != targetFolder.Folder)
              return true;
          }
        }
      }
      else
      {
        var sourceFolder = data.GetData<IFolderViewModel>();
        if (sourceFolder != null)
        {
          if (sourceFolder.Folder == targetFolder.Folder)
            return false;

          if (targetFolder.Folder.IsDescendantOf(sourceFolder.Folder))
            return false;

          return true;
        }
      }

      return false;
    }

    public void Drop(IFolderViewModel targetFolder, IDataObject data)
    {
      var messages = data.GetData<List<IMailMessage>>();

      if (messages != null && messages.Count > 0)
      {
        foreach (IMailMessage message in messages)
        {
          if (message.ParentFolder != targetFolder.Folder)
            message.ParentFolder = targetFolder.Folder;
        }
      }
      else
      {
        var sourceFolder = data.GetData<IFolderViewModel>();
        if (sourceFolder != null)
        {
          sourceFolder.Parent.IsSelected = true;
          sourceFolder.Folder.ParentFolder = targetFolder.Folder;
          targetFolder.IsExpanded = true;

          // a new FolderViewModel was created for the source model after it was moved
          // so we need to find the new source folder
          sourceFolder = targetFolder.FindViewModelByFolder(sourceFolder.Folder);
          sourceFolder.IsSelected = true;
        }
      }
    }

    public bool CanDrag(IFolderViewModel sourceFolder)
    {
      return sourceFolder.Parent != null;
    }

    #endregion
  }
}
